package com.ctsi.oauth.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.token.TokenEnhancer;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;

import java.util.HashMap;
import java.util.Map;

/**
 * @Auther: zhangjw
 * @Date: 2018/7/2 01:18
 * @Description:
 */
@Configuration
public class TokenStoreConfig {

    /**
     * 使用redis存储token的配置，只有在cloud.security.oauth2.tokenStore配置为redis时生效
     */
    @Configuration
    @ConditionalOnProperty(prefix = "cloud.security.oauth2", name = "token-store", havingValue = "redis")
    public static class RedisConfig {

        @Autowired
        private RedisConnectionFactory redisConnectionFactory;

        /**
         * Redis token store token store.
         *
         * @return token store
         */
        @Bean
        public TokenStore redisTokenStore() {
            return new RedisTokenStorePatched(redisConnectionFactory);
        }

    }

    /**
     * 使用jwt时的配置，默认生效
     *
     * @author zhangjw
     */
    @Configuration
    @ConditionalOnProperty(prefix = "cloud.security.oauth2", name = "token-store", havingValue = "jwt")
    @Import(TokenStoreProperties.class)
    public static class JwtConfig {

        @Autowired
        private TokenStoreProperties tokenStoreProperties;

        /**
         * Jwt token store token store.
         *
         * @return the token store
         */
        @Bean
        public TokenStore jwtTokenStore() {
            return new JwtTokenStore(jwtAccessTokenConverter());
        }

        /**
         * Jwt access token converter jwt access token converter.
         *
         * @return the jwt access token converter
         */
        @Bean
        public JwtAccessTokenConverter jwtAccessTokenConverter() {
            JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
            converter.setSigningKey(tokenStoreProperties.getJwtSigningKey());
            return converter;
        }

        /**
         * Jwt token enhancer token enhancer.
         *
         * @return the token enhancer
         */
        @Bean
        @ConditionalOnBean(TokenEnhancer.class)
        public TokenEnhancer jwtTokenEnhancer() {
            return new TokenEnhancer() {
                @Override
                public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication oAuth2Authentication) {
                    Map<String, Object> info = new HashMap<>(8);
                    info.put("timestamp", System.currentTimeMillis());
                    Authentication authentication = oAuth2Authentication.getUserAuthentication();
                    if (authentication != null && authentication.getPrincipal() instanceof UserDetails) {
                        Object principal = authentication.getPrincipal();
                        info.put("loginName", ((UserDetails) principal).getUsername());
                    }

                    ((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(info);

                    return accessToken;
                }
            };
        }

    }


}

